
/******************************************************************************
 * Header file inclusions.
 ******************************************************************************/

#include <avr/io.h>

#include "Arduino.h"
#include <LiquidCrystal.h>
//#include <SD.h>

// Workaround for http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34734
#ifdef PROGMEM
#undef PROGMEM
#define PROGMEM __attribute__((section(".progmem.data")))
#endif

#define SERIAL_BAUD 9600
#define chipSelect 10

#if 1
#include "FreeRTOS.h"
#include "task.h"
//#include "semphr.h"
#include "debug.h"
#else
#include "FreeRTOS_AVR.h"
#endif

#define LOGGER_BUFFSIZE 16

unsigned int temperature = 22;

//
// software serial #1: TX = digital pin 2, RX = digital pin 3
//
//SoftwareSerial serial(2, 3);

//
// Initialize the LCD: command on bottom of board-plate
//
LiquidCrystal lcd(8,9,4,5,6,7);

//File logfile;

// ==========================================================================
//   vTemperatureTask
//
//   Reading luminosity sensor value
// ==========================================================================
static void vTemperatureTask(void * pvParameters) 
{
  char buffer[LOGGER_BUFFSIZE];
  char c;
  int bufferidx = 0;

  //vTaskSetApplicationTaskTag(NULL, (BaseType_t(*)(void *)) 2);

  while(1) {

    //if (xSemaphoreTake(xSemaphoreTemperature, portMAX_DELAY == pdTRUE)) {
      //temperature = analogRead(temperatureSensorPin );
      temperature += 1;
      if (temperature >= 30) {
	temperature = 22;
      }
      //  xSemaphoreGive(xSemaphoreTemperature );
      //}

      Serial.print (F("Temperature: "));
      Serial.println (temperature, DEC);

#if 0
    //
    // read into program buffer, increment index
    //
    if (Serial.available()) {
      //digitalWrite(Green, LOW);
      c = Serial.read();

      //if (analogRead(opticalSwitchSensorPin) > 50) {
      //opticalSwitch = 1;
      //Serial.println("Error");
      //}
      //else {
      //opticalSwitch = 0;
      //}

      buffer[bufferidx++] = c;  // Store character in array and increment index

      // CR record termination or buffer full? (CR+LF is common, so don't check both)
      // See notes section regarding this implementation:
      if (c == '\r' || (bufferidx >= LOGGER_BUFFSIZE-1)) {
        buffer[bufferidx] = 0; // terminate it with null at current index
        //digitalWrite(Green, HIGH);digitalWrite(Blue, LOW);
        logfile.write((uint8_t *) buffer, (bufferidx + 1)); //write the program buffer to SD lib backend buffer
        logfile.flush();
        bufferidx = 0;     // reset buffer pointer
      }
    }
#endif // 0

    vTaskDelay(configTICK_RATE_HZ); //10ms
  }

  return;
}

#if 0
// ==========================================================================
//   vTemperatureLoggerTask
// ==========================================================================
static void vTemperatureLoggerTask (void * pvParameters)
{
  char buffer[LOGGER_BUFFSIZE];
  char c;
  int bufferidx = 0;

  vTaskSetApplicationTaskTag(NULL, (BaseType_t(*)(void *))4);

  while(1) {

#if 0
    //
    // read into program buffer, increment index
    //
    if (Serial.available()) {
      //digitalWrite(Green, LOW);
      c = Serial.read();

      //if (analogRead(opticalSwitchSensorPin) > 50) {
      //opticalSwitch = 1;
      //Serial.println("Error");
      //}
      //else {
      //opticalSwitch = 0;
      //}

      buffer[bufferidx++] = c;  // Store character in array and increment index

      // CR record termination or buffer full? (CR+LF is common, so don't check both)
      // See notes section regarding this implementation:
      if (c == '\r' || (bufferidx >= LOGGER_BUFFSIZE-1)) {
        buffer[bufferidx] = 0; // terminate it with null at current index
        //digitalWrite(Green, HIGH);digitalWrite(Blue, LOW);
        logfile.write((uint8_t *) buffer, (bufferidx + 1)); //write the program buffer to SD lib backend buffer
        logfile.flush();
        bufferidx = 0;     // reset buffer pointer
      }
    }
#endif // 0

    //vTaskDelay(configTICK_RATE_HZ/100); //10ms
    vTaskDelay(configTICK_RATE_HZ);
  }

  vTaskDelete( NULL );
}

// ==========================================================================
//   vIdleTask
// ==========================================================================
void vIdleTask (void * pvParameters)
{
  //vTaskSetApplicationTaskTag(NULL, (BaseType_t(*)(void *))6);

  while(1) {

    Serial.println(F("Idle ..."));

    vTaskDelay(configTICK_RATE_HZ);

  }

  return;
}
#endif // 0

/******************************************************************************
 * Public function definitions.
 ******************************************************************************/

void setup ()
{
  // Insure malloc works in tasks
  __malloc_heap_end = (char*)RAMEND;

  //
  // LCD dimentions
  //
  lcd.begin(16,2);
  lcd.clear();      // this clears the LCD. You can use this at any time
  lcd.print(F("Yes it does!"));

  //
  // Initialization of the serial communication with 9600kbits as baud rate
  //
  Serial.begin(SERIAL_BAUD);

  Serial.print(F("Serial init at "));
  Serial.print(SERIAL_BAUD, DEC);
  Serial.println(F(" BAUD"));

  //lcd.noDisplay();

  // discard any random input
  //while (Serial.read() >= 0) {}

  //
  // create temperature measurement task
  //
  xTaskCreate(vTemperatureTask ,
	      "T",
	      configMINIMAL_STACK_SIZE + LOGGER_BUFFSIZE*sizeof(char),
	      NULL,
	      tskIDLE_PRIORITY + 1 ,
	      NULL ) ;


  Serial.println(F("(c) 2014 Arthur: Temperature Data Logger"));

#if 0
  //
  // see if the card is present and can be initialized:
  //
  if (!SD.begin(chipSelect)) {
    Serial.println (F("Card initialization failed!"));
#if 0
    // Flash Red LED to indicate error, wait 5 sec, reboot
    int i = millis() + 5000; // 5 seconds
    Serial.println(F("Insert card or reseat card now.  Reset pending..."));
    do {
        digitalWrite(Red, LOW); delay(250); digitalWrite(Red, HIGH); delay(250);
     } while(  i > millis() );
    Serial.println("Reset!");
    delay(250);
    resetFunc();  //call reset function to reboot Arduino code
#endif
  }

  else {
    // Open the SD card logfile by name, either Create, Open, Append
    logfile = SD.open("l.txt", O_CREAT | O_WRITE | O_APPEND);
    // Test to ensure the file pointer was correctly set
    if (!logfile) {
#if 0
      int i = millis() + 5000; // 5 seconds
      Serial.print(F("Could not open logfile \n\r"));
      do {
        digitalWrite(Red, LOW); delay(250); digitalWrite(Red, HIGH); delay(250);
      } while( i > millis() ); // stay in error loop for 5 seconds
      Serial.println(F("Card write failed!  Halted..."));
      do; while(true); // halt
#endif
    } 
    else {
      Serial.println(F("Writing to: europa.txt")); 
      Serial.println(F("Ready to accept serial data..."));
    }
  }

  xTaskCreate(vIdleTask ,
	      "Idle",
	      configMINIMAL_STACK_SIZE + 50 ,
	      NULL,
	      tskIDLE_PRIORITY ,
	      NULL ) ;
#endif // 0

#if 0  
  lcd.setCursor(0,0);
  // positions starting point on LCD, column 0, row 0 (that is, the top left of our LCD)
  lcd.print("Hello!");
  // prints "Hello" at the LCD's cursor position defined above
  lcd.setCursor(0,1);
  // positions starting point on LCD, column 0, row 1 (that is, the bottom left of our LCD)
  lcd.println("This is fun     ");
  lcd.noDisplay(); // turns off the display, leaving currently-displayed data as is
#endif // 0

  Serial.println (F("Die"));

  return;
}

/**************************************************************************//**
 * \fn int main(void)
 *
 * \brief Main function.
 *
 * \return
 ******************************************************************************/
int main(void)
{
  //
  // Arduino pattern: /usr/share/arduino/hardware/arduino/cores/arduino/main.cpp
  //

  init();

#if defined(USBCON)
  USB.attach();
#endif

  setup();
  //for (;;) {
  //  loop();
  //  if (serialEventRun) serialEventRun();
  //}
  //
  // We start FreeRTOS here
  //
  vTaskStartScheduler ();
  
  return 0;
}

extern "C" {
/**************************************************************************//**
 * \fn static vApplicationIdleHook(void)
 *
 * \brief
 ******************************************************************************/
void vApplicationIdleHook(void)
{
  Serial.println(F("Idle Hook"));
}

void USARTWriteChar (char data)
{
   //Wait until the transmitter is ready

   while(!(UCSRA & (1<<UDRE))) {
      //Do nothing
   }

   //Now write the data to USART buffer

   UDR=data;
}

void vApplicationTickHook (void) 
{
  USARTWriteChar('t');
  USARTWriteChar('i');
  USARTWriteChar('c');
  USARTWriteChar('k');
  USARTWriteChar('\n');
  
  //static int32_t tick = 0;
  //Serial.print(F("Tick: "));
  //Serial.println(tick,DEC);
  //tick++;
  
}

#if 0
void vApplicationStackOverflowHook( TaskHandle_t xTask,
                                    signed char *pcTaskName )
{
  Serial.println(F("Stack overflow"));
}
#endif

void myTraceMalloc(void *addr, size_t size)
{
  Serial.print(F("Malloc: "));
  Serial.print((uint32_t)addr,HEX);
  Serial.print(F(",  "));
  Serial.println(size,DEC);
}

}
